// fileName      :  config.go
// createdAt     :  2021-09-27
// description   :	全局配置

package config

import (
	"flag"
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"log"
	"os"
	"zl-gin/utils"
)

type mysql struct {
	Port     string `mapstructure:"port"`
	Host     string `mapstructure:"host"`
	UserName string `mapstructure:"user_name"`
	Password string `mapstructure:"password"`
	DbName   string `mapstructure:"db_name"`
}

type redis struct {
	Port     string `mapstructure:"port"`
	Host     string `mapstructure:"host"`
	Db       int    `mapstructure:"db"`
	Password string `mapstructure:"password"`
	PollSize int    `mapstructure:"poll_size"`
}

type logs struct {
	FileName string `mapstructure:"file_name"`
	LogLevel string `mapstructure:"log_level"`
	Output   string `mapstructure:"output"`
	LogFile  string `mapstructure:"log_file"`
	LogDir   string `mapstructure:"log_dir"`
}

type jwt struct {
	Expire string `mapstructure:"expire"`
	Secret string `mapstructure:"secret"`
}

type gorm struct {
	MaxIdleConnection int    `mapstructure:"max_idle_connection"`
	MaxOpenCount      int    `mapstructure:"max_open_count"`
	EnableLog         bool   `mapstructure:"enable_log"`
	Output            string `mapstructure:"output"`
	LogFile           string `mapstructure:"log_file"`
	LogDir            string `mapstructure:"log_dir"`
}
type eureka struct {
	Zone    string `mapstructure:"zone"`
	TimeOut int64  `mapstructure:"timeout"`
}
type conf struct {
	AppName string `mapstructure:"app_name"`
	AppPort int    `mapstructure:"app_port"`
	AppEnv  string `mapstructure:"app_env"`
	Mysql   mysql  `mapstructure:"mysql"`
	Redis   redis  `mapstructure:"redis"`
	Log     logs   `mapstructure:"log"`
	Jwt     jwt    `mapstructure:"jwt"`
	Gorm    gorm   `mapstructure:"gorm"`
	Eureka  eureka `mapstructure:"eureka"`
}

var config *conf

func InitConfig(env string) {
	log.Println("init config...")

	//以flag的方式解析配置文件，默认为执行目录下 config/config.yaml
	systemEnv := utils.GetEnv(env)

	file := fmt.Sprintf("config/%s/config.yaml", systemEnv)
	configFile := flag.String("config_file", file, "-config_file=/path/to/config_file")
	flag.Parse()

	//检查配置文件是否存在
	_, ok := os.Stat(*configFile)
	if ok != nil {
		log.Fatalln("配置文件不存在")
	}

	//将数据解析到结构体内
	viper.SetConfigFile(*configFile)
	if err := viper.ReadInConfig(); err != nil {
		log.Fatalln(err)
	}

	config = &conf{}
	if err := viper.Unmarshal(config); err != nil {
		log.Fatalln(err)
	}

	//监视文件变化，并重新unmarshal
	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		log.Println("配置文件被修改...")
		if err := viper.Unmarshal(config); err != nil {
			panic(err)
		}
	})
	config.AppEnv = env
}

func Get() *conf {
	return config
}
